﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;

namespace WinAPI.RegistryUtility
{
    public class RegistryOperation
    {
        //  Registry.ClassesRoot 对应于HKEY_CLASSES_ROOT主键
        //  Registry.CurrentUser 对应于HKEY_CURRENT_USER主键
        //  Registry.LocalMachine 对应于 HKEY_LOCAL_MACHINE主键
        //  Registry.User 对应于 HKEY_USER主键
        //  Registry.CurrentConfig 对应于HEKY_CURRENT_CONFIG主键
        //  Registry.DynDa 对应于HKEY_DYN_DATA主键
        //  Registry.PerformanceData 对应于HKEY_PERFORMANCE_DATA主键

        //  RegistryKey类封装了对注册表的基本操作，包括读取，写入，删除。其中读取的主要函数有：

        //  OpenSubKey ( string name )方法主要是打开指定的子键。
        //  GetSubKeyNames ( )方法是获得主键下面的所有子键的名称，它的返回值是一个字符串数组。
        //  GetValueNames ( )方法是获得当前子键中的所有的键名称，它的返回值也是一个字符串数组。
        //  GetValue ( string name )方法是指定键的键值。

        //  写入的函数有：

        //  CreateSubKey（string name）方法是增加一个子键

        //  SetValue（string name,string value）方法是设置一个键的键值


        //  删除的函数：

        //  DeleteSubKey ( )方法：删除一个指定的子键。

        //  DeleteSubKeyTree ( )方法：

        //  此方法是彻底删除指定的子键目录，即：删除该子键以及该子键以下的全部子键。


        public static string[] RootNames = {
                                               "HKEY_CLASSES_ROOT", "HKEY_CURRENT_CONFIG", "HKEY_DYN_DATA", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE",
                                               "HKEY_PERFORMANCE_DATA", "HKEY_USERS"
                                           };


        public static RegistryKey GetKey(string keyName)
        {
            string[] path = keyName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
            if (!(path.Length > 0 && ValidateRootName(path[0])))
            {
                RegistryException e = new RegistryException(RegistryErrorCode.NotValidRoot);
                throw (e);
            }
            RegistryKey rootKey = GetRootKey(path[0]);
            string subKeyName = keyName.Substring(keyName.IndexOf("\\") + 1);
            RegistryKey targetKey = rootKey.OpenSubKey(subKeyName);
            rootKey.Close(); ;
            return targetKey;
        }
        public static object GetKeyValue(string keyName, string name)
        {
            RegistryKey targeyKey = GetKey(keyName);
            if (targeyKey != null)
            {
                object value = targeyKey.GetValue(name);
                targeyKey.Close();
                return value;
            }
            return null;
        }
        public static object GetKeyValue(RegistryKey targeyKey, string name)
        {

            if (targeyKey != null)
            {
                return targeyKey.GetValue(name);
            }
            return null;
        }
        public static RegistryValueKind GetKeyType(string keyName, string name)
        {
            RegistryKey targeyKey = GetKey(keyName);
            if (targeyKey != null)
            {
                RegistryValueKind type = targeyKey.GetValueKind(name);
                targeyKey.Close();
                return type;
            }
            return RegistryValueKind.Unknown;
        }
        public static RegistryValueKind GetKeyType(RegistryKey targeyKey, string name)
        {
            if (targeyKey != null)
            {
                return targeyKey.GetValueKind(name);
            }
            return RegistryValueKind.Unknown;
        }



        private static bool ValidateRootName(string rootName)
        {
            rootName = rootName.ToUpper();
            for (int i = RootNames.Length - 1; i >= 0; i--)
            {
                if (rootName == RootNames[i])
                    return true;
            }
            return false;
        }

        private static RegistryHive GetRemoteRootKey(string rootName)
        {
            rootName = rootName.ToLower();
            RegistryHive rootKey;
            switch (rootName)
            {
                case "classesroot":
                    rootKey = RegistryHive.ClassesRoot;
                    break;
                case "currentconfig":
                    rootKey = RegistryHive.CurrentConfig;
                    break;
                case "currentuser":
                    rootKey = RegistryHive.CurrentUser;
                    break;
                case "dyndata":
                    rootKey = RegistryHive.DynData;
                    break;
                case "localmachine":
                    rootKey = RegistryHive.LocalMachine;
                    break;
                case "performancedata":
                    rootKey = RegistryHive.PerformanceData;
                    break;
                case "users":
                    rootKey = RegistryHive.Users;
                    break;
                default:
                    rootKey = RegistryHive.LocalMachine;
                    break;
            }
            return rootKey;
        }
        private static RegistryKey GetRootKey(string rootName)
        {
            rootName = rootName.ToUpper();
            RegistryKey rootKey;
            switch (rootName)
            {
                case "HKEY_CLASSES_ROOT":
                    rootKey = Registry.ClassesRoot;
                    break;
                case "HKEY_CURRENT_CONFIG":
                    rootKey = Registry.CurrentConfig;
                    break;
                case "HKEY_CURRENT_USER":
                    rootKey = Registry.CurrentUser;
                    break;
                case "HKEY_DYN_DATA":
                    rootKey = Registry.DynData;
                    break;
                case "HKEY_LOCAL_MACHINE":
                    rootKey = Registry.LocalMachine;
                    break;
                case "HKEY_PERFORMANCE_DATA":
                    rootKey = Registry.PerformanceData;
                    break;
                case "HKEY_USERS":
                    rootKey = Registry.Users;
                    break;
                default:
                    rootKey = Registry.LocalMachine;
                    break;
            }
            return rootKey;
        }
    }

    public enum RegistryErrorCode
    {
        NoError,
        NotValidRoot
    }

    public class RegistryException : Exception
    {
        private readonly RegistryErrorCode errorCode = RegistryErrorCode.NoError;
        private readonly string errorDescription = string.Empty;

        public RegistryException(RegistryErrorCode errorCode)
        {
            this.errorCode = errorCode;
        }

        public RegistryException(RegistryErrorCode errorCode, string errorDescription)
        {
            this.errorDescription = errorDescription;
            this.errorCode = errorCode;
        }

        public RegistryErrorCode ErrorCode
        {
            get { return errorCode; }
        }

        public string ErrorDescription
        {
            get { return errorDescription; }
        }
    }
}
